<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>JavaKeeper</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/icon.svg">
    <script>
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?a949a9b30eb86ac0159e735ff8670c03";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
            // 引入谷歌,不需要可删除这段
            var hm1 = document.createElement("script");
            hm1.src = "https://www.googletagmanager.com/gtag/js?id=UA-169923503-1";
            var s1 = document.getElementsByTagName("script")[0]; 
            s1.parentNode.insertBefore(hm1, s1);
        })();
        // 谷歌加载,不需要可删除
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-169923503-1');
    </script>
    <meta name="description" content="">
    <meta name="keywords" content="JavaKeeper,Java,Java开发,算法,blog">
    <link rel="preload" href="/assets/css/0.styles.91f57736.css" as="style"><link rel="preload" href="/assets/js/app.447d4224.js" as="script"><link rel="preload" href="/assets/js/3.9d76740c.js" as="script"><link rel="preload" href="/assets/js/1.c4fd7d2e.js" as="script"><link rel="preload" href="/assets/js/106.a6cb54b0.js" as="script"><link rel="prefetch" href="/assets/js/10.8cf3be2c.js"><link rel="prefetch" href="/assets/js/100.74f35ab8.js"><link rel="prefetch" href="/assets/js/101.7a062346.js"><link rel="prefetch" href="/assets/js/102.c9485235.js"><link rel="prefetch" href="/assets/js/103.d88a3805.js"><link rel="prefetch" href="/assets/js/104.6e034144.js"><link rel="prefetch" href="/assets/js/105.d22f7450.js"><link rel="prefetch" href="/assets/js/107.7b65e72b.js"><link rel="prefetch" href="/assets/js/108.eb5804bb.js"><link rel="prefetch" href="/assets/js/109.05f775e5.js"><link rel="prefetch" href="/assets/js/11.c54ae13c.js"><link rel="prefetch" href="/assets/js/110.51d3d641.js"><link rel="prefetch" href="/assets/js/111.022b64a7.js"><link rel="prefetch" href="/assets/js/112.da8afd52.js"><link rel="prefetch" href="/assets/js/113.05a17b18.js"><link rel="prefetch" href="/assets/js/114.8960d913.js"><link rel="prefetch" href="/assets/js/115.67919f68.js"><link rel="prefetch" href="/assets/js/116.62b0cd71.js"><link rel="prefetch" href="/assets/js/117.ebac3eff.js"><link rel="prefetch" href="/assets/js/118.ecd629bd.js"><link rel="prefetch" href="/assets/js/119.a09a0897.js"><link rel="prefetch" href="/assets/js/12.60aa3b24.js"><link rel="prefetch" href="/assets/js/120.bf639d3d.js"><link rel="prefetch" href="/assets/js/121.b89d0c8e.js"><link rel="prefetch" href="/assets/js/122.1a75ff83.js"><link rel="prefetch" href="/assets/js/123.d2127132.js"><link rel="prefetch" href="/assets/js/124.2caff9e0.js"><link rel="prefetch" href="/assets/js/125.9b9f966a.js"><link rel="prefetch" href="/assets/js/126.58cdfb3d.js"><link rel="prefetch" href="/assets/js/127.8ef09c53.js"><link rel="prefetch" href="/assets/js/128.efdc2ae4.js"><link rel="prefetch" href="/assets/js/129.e35cbc57.js"><link rel="prefetch" href="/assets/js/13.125c13a0.js"><link rel="prefetch" href="/assets/js/130.f01a55e3.js"><link rel="prefetch" href="/assets/js/131.65205f4a.js"><link rel="prefetch" href="/assets/js/132.f42c5a0a.js"><link rel="prefetch" href="/assets/js/133.9ba468b3.js"><link rel="prefetch" href="/assets/js/134.7b597ba9.js"><link rel="prefetch" href="/assets/js/135.fb828b9a.js"><link rel="prefetch" href="/assets/js/136.3887532f.js"><link rel="prefetch" href="/assets/js/137.549bae01.js"><link rel="prefetch" href="/assets/js/138.db8d423d.js"><link rel="prefetch" href="/assets/js/139.dbaf2267.js"><link rel="prefetch" href="/assets/js/14.bd1d0b0d.js"><link rel="prefetch" href="/assets/js/140.6cb65fdc.js"><link rel="prefetch" href="/assets/js/141.9bd6cc4b.js"><link rel="prefetch" href="/assets/js/142.552db5ed.js"><link rel="prefetch" href="/assets/js/143.2c9f2bf4.js"><link rel="prefetch" href="/assets/js/144.fba98a15.js"><link rel="prefetch" href="/assets/js/145.c42f3a21.js"><link rel="prefetch" href="/assets/js/146.596d4d33.js"><link rel="prefetch" href="/assets/js/147.c48ae5c1.js"><link rel="prefetch" href="/assets/js/148.71064871.js"><link rel="prefetch" href="/assets/js/149.16582d21.js"><link rel="prefetch" href="/assets/js/15.f247873b.js"><link rel="prefetch" href="/assets/js/150.ead09aca.js"><link rel="prefetch" href="/assets/js/151.971fdf4b.js"><link rel="prefetch" href="/assets/js/152.369c9362.js"><link rel="prefetch" href="/assets/js/153.371edd15.js"><link rel="prefetch" href="/assets/js/154.e090b491.js"><link rel="prefetch" href="/assets/js/155.c68bf602.js"><link rel="prefetch" href="/assets/js/156.304aea8d.js"><link rel="prefetch" href="/assets/js/157.83beef7f.js"><link rel="prefetch" href="/assets/js/158.bb1794b0.js"><link rel="prefetch" href="/assets/js/159.2d54e792.js"><link rel="prefetch" href="/assets/js/16.04336c71.js"><link rel="prefetch" href="/assets/js/160.99d56586.js"><link rel="prefetch" href="/assets/js/161.edf660aa.js"><link rel="prefetch" href="/assets/js/162.0b84606e.js"><link rel="prefetch" href="/assets/js/163.b59e0d60.js"><link rel="prefetch" href="/assets/js/164.d9eb8228.js"><link rel="prefetch" href="/assets/js/165.ca624c79.js"><link rel="prefetch" href="/assets/js/166.025b2ba1.js"><link rel="prefetch" href="/assets/js/167.abc982cc.js"><link rel="prefetch" href="/assets/js/168.27ca13dc.js"><link rel="prefetch" href="/assets/js/169.41e753a2.js"><link rel="prefetch" href="/assets/js/17.43b3c1c8.js"><link rel="prefetch" href="/assets/js/170.626319e1.js"><link rel="prefetch" href="/assets/js/171.a221dddf.js"><link rel="prefetch" href="/assets/js/172.464b2361.js"><link rel="prefetch" href="/assets/js/173.96a3afee.js"><link rel="prefetch" href="/assets/js/174.116607c2.js"><link rel="prefetch" href="/assets/js/175.ea3e8659.js"><link rel="prefetch" href="/assets/js/176.7d7b8afc.js"><link rel="prefetch" href="/assets/js/177.a6e00aa0.js"><link rel="prefetch" href="/assets/js/178.1f93afaf.js"><link rel="prefetch" href="/assets/js/179.3aa00dcd.js"><link rel="prefetch" href="/assets/js/18.d81b44d5.js"><link rel="prefetch" href="/assets/js/180.f8b2b75a.js"><link rel="prefetch" href="/assets/js/181.8e11258a.js"><link rel="prefetch" href="/assets/js/182.22243941.js"><link rel="prefetch" href="/assets/js/183.d051fdf6.js"><link rel="prefetch" href="/assets/js/184.a994075e.js"><link rel="prefetch" href="/assets/js/185.776c7e16.js"><link rel="prefetch" href="/assets/js/186.f1887955.js"><link rel="prefetch" href="/assets/js/187.da0d3626.js"><link rel="prefetch" href="/assets/js/188.8dfc358f.js"><link rel="prefetch" href="/assets/js/189.dcac5a59.js"><link rel="prefetch" href="/assets/js/19.1b3d66e1.js"><link rel="prefetch" href="/assets/js/190.c7e413d0.js"><link rel="prefetch" href="/assets/js/191.d9806121.js"><link rel="prefetch" href="/assets/js/192.869791da.js"><link rel="prefetch" href="/assets/js/193.2d74c4c8.js"><link rel="prefetch" href="/assets/js/194.c73a1909.js"><link rel="prefetch" href="/assets/js/195.e8c74834.js"><link rel="prefetch" href="/assets/js/20.bd5949ec.js"><link rel="prefetch" href="/assets/js/21.3fcf98cf.js"><link rel="prefetch" href="/assets/js/22.2fa1e2e8.js"><link rel="prefetch" href="/assets/js/23.1ae64bb4.js"><link rel="prefetch" href="/assets/js/24.7bdf7387.js"><link rel="prefetch" href="/assets/js/25.392c436e.js"><link rel="prefetch" href="/assets/js/26.58acbd4b.js"><link rel="prefetch" href="/assets/js/27.c725bdd5.js"><link rel="prefetch" href="/assets/js/28.6c9bda1e.js"><link rel="prefetch" href="/assets/js/29.e656b537.js"><link rel="prefetch" href="/assets/js/30.2c326fc7.js"><link rel="prefetch" href="/assets/js/31.e6c9fa30.js"><link rel="prefetch" href="/assets/js/32.c9c88437.js"><link rel="prefetch" href="/assets/js/33.0c53373c.js"><link rel="prefetch" href="/assets/js/34.9821e543.js"><link rel="prefetch" href="/assets/js/35.de8253eb.js"><link rel="prefetch" href="/assets/js/36.d182f929.js"><link rel="prefetch" href="/assets/js/37.9fa79014.js"><link rel="prefetch" href="/assets/js/38.9bebff76.js"><link rel="prefetch" href="/assets/js/39.19a3a2d4.js"><link rel="prefetch" href="/assets/js/4.564edb9d.js"><link rel="prefetch" href="/assets/js/40.cca6955f.js"><link rel="prefetch" href="/assets/js/41.854cd09a.js"><link rel="prefetch" href="/assets/js/42.ca7b612f.js"><link rel="prefetch" href="/assets/js/43.87027d58.js"><link rel="prefetch" href="/assets/js/44.8c2b4f4b.js"><link rel="prefetch" href="/assets/js/45.dffb4e08.js"><link rel="prefetch" href="/assets/js/46.f58049a5.js"><link rel="prefetch" href="/assets/js/47.6854070c.js"><link rel="prefetch" href="/assets/js/48.6cd9fa3d.js"><link rel="prefetch" href="/assets/js/49.e8861afa.js"><link rel="prefetch" href="/assets/js/5.5c31d62f.js"><link rel="prefetch" href="/assets/js/50.703bffab.js"><link rel="prefetch" href="/assets/js/51.6655c373.js"><link rel="prefetch" href="/assets/js/52.deb2eb09.js"><link rel="prefetch" href="/assets/js/53.6e0ed77d.js"><link rel="prefetch" href="/assets/js/54.b05c58ad.js"><link rel="prefetch" href="/assets/js/55.49c8164e.js"><link rel="prefetch" href="/assets/js/56.a5574e6b.js"><link rel="prefetch" href="/assets/js/57.58cb0de4.js"><link rel="prefetch" href="/assets/js/58.52345112.js"><link rel="prefetch" href="/assets/js/59.663ce78d.js"><link rel="prefetch" href="/assets/js/6.a9df34ee.js"><link rel="prefetch" href="/assets/js/60.f06adde2.js"><link rel="prefetch" href="/assets/js/61.170255a1.js"><link rel="prefetch" href="/assets/js/62.9d120050.js"><link rel="prefetch" href="/assets/js/63.70cced6b.js"><link rel="prefetch" href="/assets/js/64.577f3548.js"><link rel="prefetch" href="/assets/js/65.c037b29d.js"><link rel="prefetch" href="/assets/js/66.7dd1045f.js"><link rel="prefetch" href="/assets/js/67.d3aa4d6c.js"><link rel="prefetch" href="/assets/js/68.526dbb61.js"><link rel="prefetch" href="/assets/js/69.58269266.js"><link rel="prefetch" href="/assets/js/7.6609d4d6.js"><link rel="prefetch" href="/assets/js/70.64108f1b.js"><link rel="prefetch" href="/assets/js/71.1e95e0a6.js"><link rel="prefetch" href="/assets/js/72.42e7ec94.js"><link rel="prefetch" href="/assets/js/73.dad4e1c5.js"><link rel="prefetch" href="/assets/js/74.28ea286a.js"><link rel="prefetch" href="/assets/js/75.dd6d4c6f.js"><link rel="prefetch" href="/assets/js/76.ca6539df.js"><link rel="prefetch" href="/assets/js/77.feb13b0e.js"><link rel="prefetch" href="/assets/js/78.321e90e6.js"><link rel="prefetch" href="/assets/js/79.68eb8fcf.js"><link rel="prefetch" href="/assets/js/8.396d51fd.js"><link rel="prefetch" href="/assets/js/80.4edb5321.js"><link rel="prefetch" href="/assets/js/81.735d7e57.js"><link rel="prefetch" href="/assets/js/82.fa120bdf.js"><link rel="prefetch" href="/assets/js/83.bf755f94.js"><link rel="prefetch" href="/assets/js/84.9b32070c.js"><link rel="prefetch" href="/assets/js/85.592aca7c.js"><link rel="prefetch" href="/assets/js/86.4dcd9e73.js"><link rel="prefetch" href="/assets/js/87.a9e546aa.js"><link rel="prefetch" href="/assets/js/88.2a423212.js"><link rel="prefetch" href="/assets/js/89.5f455115.js"><link rel="prefetch" href="/assets/js/9.adb074c6.js"><link rel="prefetch" href="/assets/js/90.5202da0a.js"><link rel="prefetch" href="/assets/js/91.02cee99d.js"><link rel="prefetch" href="/assets/js/92.f16bad0b.js"><link rel="prefetch" href="/assets/js/93.f933634f.js"><link rel="prefetch" href="/assets/js/94.8e7b1d65.js"><link rel="prefetch" href="/assets/js/95.ee0e4a0a.js"><link rel="prefetch" href="/assets/js/96.e21d78c2.js"><link rel="prefetch" href="/assets/js/97.c87e514e.js"><link rel="prefetch" href="/assets/js/98.d123ac92.js"><link rel="prefetch" href="/assets/js/99.92d1b416.js">
    <link rel="stylesheet" href="/assets/css/0.styles.91f57736.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container" data-v-3ba18f14><div data-v-3ba18f14><div id="loader-wrapper" class="loading-wrapper" data-v-041fef5b data-v-3ba18f14 data-v-3ba18f14><div class="loader-main" data-v-041fef5b><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-68139a52 data-v-3ba18f14 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52>JavaKeeper</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div class="hide" data-v-3ba18f14><header class="navbar" data-v-3ba18f14><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">JavaKeeper</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link router-link-active"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask" data-v-3ba18f14></div> <aside class="sidebar" data-v-3ba18f14><div class="personal-info-wrapper" data-v-5f6acefd data-v-3ba18f14><!----> <h3 class="name" data-v-5f6acefd>
    海星
  </h3> <div class="num" data-v-5f6acefd><div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Article</h6></div> <div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Tag</h6></div></div> <hr data-v-5f6acefd></div> <nav class="nav-links"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link router-link-active"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <ul class="sidebar-links"><li><a href="/interview/Collections-FAQ.html" class="sidebar-link">Java集合面试</a></li><li><a href="/interview/JUC-FAQ.html" class="sidebar-link">Java 多线程面试</a></li><li><a href="/interview/JVM-FAQ.html" class="sidebar-link">JVM 面试</a></li><li><a href="/interview/MySQL-FAQ.html" class="sidebar-link">MySQL 面试</a></li><li><a href="/interview/Redis-FAQ.html" class="sidebar-link">Redis 面试</a></li><li><a href="/interview/Network-FAQ.html" aria-current="page" class="active sidebar-link">计算机网络面试</a></li><li><a href="/interview/Kafka-FAQ.html" class="sidebar-link">Kafka 面试</a></li><li><a href="/interview/ZooKeeper-FAQ.html" class="sidebar-link">Zookeeper 面试</a></li><li><a href="/interview/MyBatis-FAQ.html" class="sidebar-link">MyBatis 面试</a></li><li><a href="/interview/Spring-FAQ.html" class="sidebar-link">Spring 面试</a></li><li><a href="/interview/Design-Pattern-FAQ.html" class="sidebar-link">设计模式面试</a></li><li><a href="/interview/Tomcat-FAQ.html" class="sidebar-link">Tomcat 面试</a></li></ul> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-68139a52 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52></h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div data-v-3ba18f14><main class="page"><div class="page-title" style="display:none;"><h1 class="title"></h1> <div data-v-5d8dbdb4><i class="iconfont reco-account" data-v-5d8dbdb4><span data-v-5d8dbdb4>海星</span></i> <!----> <!----> <!----></div></div> <div class="theme-reco-content content__default" style="display:none;"><blockquote><p>你好，我是 π大新，目前在一家名字等于周角的公司就职，精通Java，熟悉计算机网络，，</p></blockquote> <p>然后就~~~~</p> <blockquote><p>在浏览器中输入一个 URL 至页面呈现，网络上都发生了什么事？</p> <p>能说说 ISO 七层模型和 TCP/IP 四层模型吗？</p> <p>TCP/IP 与 HTTP 有什么关系吗？</p> <p>TCP协议与UDP协议的区别？</p> <p>请详细介绍一下 TCP 的三次握手机制，为什么要三次握手？挥手却又是四次呢？</p> <p>详细讲一下TCP的滑动窗口？知道流量控制和拥塞控制吗？</p> <p>说一下对称加密与非对称加密？</p> <p>状态码 206 是什么意思？</p> <p>你们用的 https 是吧，https 工作原理是什么？</p> <p>......</p></blockquote> <blockquote><p>文章收录在 GitHub <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer">JavaKeeper<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> ，N线互联网开发必备技能兵器谱，有你想要的。</p></blockquote> <h2 id="一、计算机网络"><a href="#一、计算机网络" class="header-anchor">#</a> 一、计算机网络</h2> <h3 id="通信协议"><a href="#通信协议" class="header-anchor">#</a> 通信协议</h3> <p>通信协议（communications protocol）是指双方实体完成通信或服务所必须遵循的规则和约定。通过通信信道和设备互连起来的多个不同地理位置的数据通信系统，要使其能协同工作实现信息交换和资源共享，它们之间必须具有共同的语言。交流什么、怎样交流及何时交流，都必须遵循某种互相都能接受的规则。这个规则就是通信协议。</p> <h3 id="网络模型"><a href="#网络模型" class="header-anchor">#</a> 网络模型</h3> <p>随着技术的发展，计算机的应用越来越广泛，计算机之间的通信开始了百花齐放的状态，每个具有独立计算服务体系的信息技术公司都会建立自己的计算机通信规则，而这种情况会导致异构计算机之间无法通信，极大的阻碍了网络通信的发展，至此为了解决这个问题，国际标准化组织（ISO）制定了OSI模型，该模型定义了不同计算机互联的标准，OSI模型把网络通信的工作分为7层，分别是<strong>物理层、数据链路层、网络层、传输层、会话层、表示层和应用层</strong>。</p> <p>这七层模型是设计层面的概念，每一层都有固定要完成的职责和功能，分层的好处在于清晰和功能独立性，但分层过多会使层次变的更加复杂，虽然不需要实现本层的功能，但是也需要构造本层的上下文，空耗系统资源，所以在落地实施网络通信模型的时候将这七层模型简化合并为四层模型分别是<strong>应用层、传输层、网络层、网络接口层</strong>（各层之间的模型、协议统称为：<strong>TCP/IP协议簇</strong>）。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds66rxwnaj30ku0dr0tn.jpg" alt=""></p> <p>从上图可以看到，TCP/IP模型合并了OSI模型的应用层、表示层和会话层，将OSI模型的数据链路层和物理层合并为网络访问层。</p> <p>上图还列出了各层模型对应TCP/IP协议栈中的协议以及各层协议之间的关系。比如DNS协议是建立在TCP和UDP协议的基础上，FTP、HTTP、TELNET协议建立在TCP协议的基础上，NTP、TFTP、SNMP建立在UDP协议的基础上，而TCP、UDP协议又建立在IP协议的基础上，以此类推….</p> <table><thead><tr><th style="text-align:left;">OSI中的层</th> <th>功能</th> <th style="text-align:left;">TCP/IP协议族</th></tr></thead> <tbody><tr><td style="text-align:left;"><strong>应用层</strong></td> <td>文件传输，电子邮件，文件服务，虚拟终端</td> <td style="text-align:left;">TFTP，HTTP，SNMP，FTP，SMTP，DNS，RIP，Telnet</td></tr> <tr><td style="text-align:left;"><strong>表示层</strong></td> <td>数据格式化，代码转换，数据加密</td> <td style="text-align:left;">无</td></tr> <tr><td style="text-align:left;"><strong>会话层</strong></td> <td>控制应用程序之间会话能力；如不同软件数据分发给不同软件</td> <td style="text-align:left;">ASAP、TLS、SSH、ISO 8327 / CCITT X.225、RPC、NetBIOS、ASP、Winsock、BSD sockets</td></tr> <tr><td style="text-align:left;"><strong>传输层</strong></td> <td>端到端传输数据的基本功能</td> <td style="text-align:left;">TCP、UDP</td></tr> <tr><td style="text-align:left;"><strong>网络层</strong></td> <td>定义IP编址，定义路由功能；如不同设备的数据转发</td> <td style="text-align:left;">IP，ICMP，RIP，OSPF，BGP，IGMP</td></tr> <tr><td style="text-align:left;"><strong>数据链路层</strong></td> <td>定义数据的基本格式，如何传输，如何标识</td> <td style="text-align:left;">SLIP，CSLIP，PPP，ARP，RARP，MTU</td></tr> <tr><td style="text-align:left;"><strong>物理层</strong></td> <td>以<strong>二进制</strong>数据形式在物理媒体上传输数据</td> <td style="text-align:left;">ISO2110，IEEE802</td></tr></tbody></table> <p>当我们某一个网站上不去的时候。通常会ping一下这个网站</p> <p><code>ping</code> 可以说是ICMP的最著名的应用，是TCP/IP协议的一部分。利用<code>ping</code>命令可以检查网络是否连通，可以很好地帮助我们分析和判定网络故障。</p> <h2 id="二、tcp-ip"><a href="#二、tcp-ip" class="header-anchor">#</a> 二、TCP/IP</h2> <p>数据在网络中传输最终一定是通过物理介质传输。物理介质就是把电脑连接起来的物理手段，常见的有光纤、双绞线，以及无线电波，它决定了电信号(0和1)的传输方式，物理介质的不同决定了电信号的传输带宽、速率、传输距离以及抗干扰性等等。网络数据传输就像快递邮寄，数据就是快件。只有路打通了，你的”快递”才能送到，因此物理介质是网络通信的基石。</p> <p>寄快递首先得称重、确认体积(确认数据大小)，贵重物品还得层层包裹填充物确保安全，封装，然后填写发件地址(源主机地址)和收件地址(目标主机地址)，确认快递方式。对于偏远地区，快递不能直达，还需要中途转发。网络通信也是一样的道理，只不过把这些步骤都规定成了各种协议。</p> <p>TCP/IP的模型的每一层都需要下一层所提供的协议来完成自己的目的。我们来看下数据是怎么通过TCP/IP协议模型从一台主机发送到另一台主机的。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds66lxjnqj30i00f6t9b.jpg" alt=""></p> <p>当用户通过HTTP协议发起一个请求，应用层、传输层、网络互联层和网络访问层的相关协议依次对该请求进行包装并携带对应的首部，最终在网络访问层生成以太网数据包，以太网数据包通过物理介质传输给对方主机，对方接收到数据包以后，然后再一层一层采用对应的协议进行拆包，最后把应用层数据交给应用程序处理。</p> <h3 id="tcp-ip-与-http"><a href="#tcp-ip-与-http" class="header-anchor">#</a> TCP/IP 与 HTTP</h3> <p>TCP/IP（Transmission Control Protocol/Internet Protocol，传输控制协议/网际协议）是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP 协议不仅仅指的是 TCP  和 IP 两个协议，而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇， 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性，所以被称为TCP/IP协议。</p> <p><strong>而HTTP是应用层协议，主要解决如何包装数据。</strong></p> <p>“IP”代表网际协议，TCP 和 UDP 使用该协议从一个网络传送数据包到另一个网络。把<strong>IP想像成一种高速公路</strong>，它允许其它协议在上面行驶并找到到其它电脑的出口。<strong>TCP和UDP是高速公路上的“卡车”，它们携带的货物就是像HTTP</strong>，文件传输协议FTP这样的协议等。</p> <h3 id="tcp-与-udp"><a href="#tcp-与-udp" class="header-anchor">#</a> TCP 与 UDP</h3> <p>都属于传输层协议。</p> <p>TCP（Transmission Control Protocol，传输控制协议）是面向连接的协议，也就是说，在收发数据前，必须和对方建立可靠的连接。一个TCP连接必须有三次握手、四次挥手。</p> <p>UDP（User Data Protocol，用户数据报协议）是一个非连接的协议，传输数据之前源端和终端不建立连接， 当它想传送时就简单地去抓取来自应用程序的数据，并尽可能快地把它扔到网络上</p> <table><thead><tr><th style="text-align:left;"></th> <th style="text-align:left;">TCP</th> <th style="text-align:left;">UDP</th></tr></thead> <tbody><tr><td style="text-align:left;">连接性</td> <td style="text-align:left;">面向连接</td> <td style="text-align:left;">面向非连接</td></tr> <tr><td style="text-align:left;">传输可靠性</td> <td style="text-align:left;">可靠</td> <td style="text-align:left;">不可靠</td></tr> <tr><td style="text-align:left;">报文</td> <td style="text-align:left;">面向字节流</td> <td style="text-align:left;">面向报文</td></tr> <tr><td style="text-align:left;">效率</td> <td style="text-align:left;">传输效率低</td> <td style="text-align:left;">传输效率高</td></tr> <tr><td style="text-align:left;">流量控制</td> <td style="text-align:left;">滑动窗口</td> <td style="text-align:left;">无</td></tr> <tr><td style="text-align:left;">拥塞控制</td> <td style="text-align:left;">慢开始、拥塞避免、快重传、快恢复</td> <td style="text-align:left;">无</td></tr> <tr><td style="text-align:left;">传输速度</td> <td style="text-align:left;">慢</td> <td style="text-align:left;">快</td></tr> <tr><td style="text-align:left;">应用场合</td> <td style="text-align:left;">对效率要求低，对准确性要求高或要求有连接的场景</td> <td style="text-align:left;">对效率要求高，对准确性要求低</td></tr></tbody></table> <p>TCP和UDP协议的一些应用</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds67b566dj30yw0r6gza.jpg" alt=""></p> <h3 id="tcp连接的建立与终止"><a href="#tcp连接的建立与终止" class="header-anchor">#</a> TCP连接的建立与终止</h3> <p>TCP虽然是面向字节流的，但TCP传送的数据单元却是报文段。一个TCP报文段分为首部和数据两部分，而TCP的全部功能体现在它首部中的各字段的作用。</p> <p>TCP报文段首部的前20个字节是固定的（下图），后面有4n字节是根据需要而增加的选项（n是整数）。因此TCP首部的最小长度是20字节。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gdr6e2kp1lj30u60jsdhn.jpg" alt=""></p> <h4 id="tcp报文首部"><a href="#tcp报文首部" class="header-anchor">#</a> TCP报文首部</h4> <ul><li>源端口和目的端口，各占2个字节，分别写入源端口和目的端口；</li> <li><strong>序列号</strong>（Sequence number），占4字节。序号范围是【0，2^32 - 1】，共2^32个序号。序号增加到 2^32-1后，下一个序号就又回到 0。TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值则是指的是本报文段所发送的数据的第一个字节的序号。例如，一报文段的序号是301，而接待的数据共有100字节。这就表明：本报文段的数据的第一个字节的序号是301，最后一个字节的序号是400。显然，下一个报文段（如果还有的话）的数据序号应当从401开始，即下一个报文段的序号字段值应为401。这个字段的序号也叫“报文段序号”;</li> <li><strong>确认号</strong>（Acknowledge number），占4个字节，是期望收到对方下一个报文的第一个数据字节的序号。例如，B收到了A发送过来的报文，其序列号字段是501，而数据长度是200字节，这表明B正确的收到了A发送的到序号700为止的数据。因此，B期望收到A的下一个数据序号是701，于是B在发送给A的确认报文段中把确认号置为701；</li> <li>数据偏移，占4位，它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。</li> <li>保留，占6位，保留为今后使用，但目前应置为0；</li> <li>紧急URG（URGent），当URG=1，表明紧急指针字段有效。告诉系统此报文段中有紧急数据；</li> <li>确认ACK（ACKnowledgment），仅当ACK=1时，确认号字段才有效。<strong>TCP规定，在连接建立后所有报文的传输都必须把ACK置1</strong>；</li> <li>推送PSH（PuSH） ，当两个应用进程进行交互式通信时，有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应，这时候就将PSH=1；</li> <li>复位RST（ReSeT），当RST=1，表明TCP连接中出现严重差错，必须释放连接，然后再重新建立连接；</li> <li>同步SYN（SYNchronization），在连接建立时用来同步序号。<strong>当SYN=1，ACK=0，表明是连接请求报文，若同意连接，则响应报文中应该使SYN=1，ACK=1</strong>；</li> <li>终止FIN（FINis），用来释放连接。<strong>当FIN=1，表明此报文的发送方的数据已经发送完毕，并且要求释放</strong>；
<ul><li>窗口，占2字节，指的是通知接收方，发送本报文你需要有多大的空间来接受；</li></ul></li> <li>检验和，占2字节，校验首部和数据这两部分；</li> <li>紧急指针，占2字节，指出本报文段中的紧急数据的字节数；</li> <li>选项，长度可变，定义一些其他的可选的参数</li></ul> <p>TCP是一种面向连接的单播协议，在发送数据前，通信双方必须在彼此间建立一条连接。所谓的“连接”，其实是客户端和服务器的内存里保存的一份关于对方的信息，如ip地址、端口号等。</p> <h4 id="tcp-三次握手"><a href="#tcp-三次握手" class="header-anchor">#</a> TCP  三次握手</h4> <p>所谓三次握手(Three-way Handshake)，是指建立一个 TCP 连接时，需要客户端和服务器总共发送3个包。</p> <p>三次握手的目的是连接服务器指定端口，建立 TCP 连接，并同步连接双方的序列号和确认号，交换 TCP 窗口大小信息。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds67rwlvsj30ra0e9n07.jpg" alt=""></p> <ul><li><p><strong>第一次握手</strong>(SYN=1, seq=x)</p> <p>建立连接。客户端发送连接请求报文段，这是报文首部中的同步位SYN=1，同时选择一个初始序列号 seq=x ，此时，客户端进程进入了 SYN-SENT（同步已发送状态）状态。TCP规定，SYN报文段（SYN=1的报文段）不能携带数据，但需要消耗掉一个序号；</p></li> <li><p><strong>第二次握手</strong>(SYN=1, ACK=1, seq=y, ACKnum=x+1)</p> <p>服务器收到客户端的SYN报文段，如果同意连接，则发出确认报文。确认报文中应该 ACK=1，SYN=1，确认号ACKnum=x+1，同时，自己还要发送SYN请求信息，SYN=1，为自己初始化一个序列号 seq=y，服务器端将上述所有信息放到一个报文段（即SYN+ACK报文段）中，一并发送给客户端，此时，TCP服务器进程进入了SYN-RCVD（同步收到）状态。这个报文也不能携带数据，但是同样要消耗一个序号</p></li> <li><p><strong>第三次握手</strong>(ACK=1，ACKnum=y+1)</p> <p>客户端收到服务器的SYN+ACK报文段，再次发送确认包(ACK)，<strong>SYN 标志位为0</strong>，ACK 标志位为1，确认号 ACKnum = y+1，这个报文段发送完毕以后，客户端和服务器端都进入ESTABLISHED（已建立连接）状态，完成TCP三次握手。</p></li></ul> <blockquote><p>为什么需要三次握手呢？两次不行吗？</p></blockquote> <p>为了防止已失效的连接请求报文段突然又传送到了服务端，因而产生错误。</p> <p>具体例子：“已失效的连接请求报文段”的产生在这样一种情况下：client发出的第一个连接请求报文段并没有丢失，而是在某个网络结点长时间的滞留了，以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后，就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段，同意建立连接。假设不采用“三次握手”，那么只要server发出确认，新的连接就建立了。由于现在client并没有发出建立连接的请求，因此不会理睬server的确认，也不会向server发送数据。但server却以为新的运输连接已经建立，并一直等待client发来数据。这样，server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况，client不会向server的确认发出确认。server由于收不到确认，就知道client并没有要求建立连接。”</p> <h4 id="tcp-四次挥手"><a href="#tcp-四次挥手" class="header-anchor">#</a> TCP  四次挥手</h4> <p>TCP 的连接的拆除需要发送四个包，因此称为四次挥手(Four-way handshake)，也叫做改进的三次握手。<strong>客户端或服务器均可主动发起挥手动作</strong>。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds6835mzjj30qw0g4dit.jpg" alt=""></p> <ul><li><p>第一次挥手(FIN=1，seq=x)</p> <p>主机1（可以使客户端，也可以是服务器端），设置seq=x，向主机2发送一个FIN报文段；此时，主机1进入<code>FIN_WAIT_1</code>状态；这表示主机1没有数据要发送给主机2了；</p></li> <li><p>第二次挥手(ACK=1，ACKnum=x+1)</p> <p>主机2收到了主机1发送的FIN报文段，向主机1回一个ACK报文段，Acknnum=x+1，主机1进入<code>FIN_WAIT_2</code>状态；主机2告诉主机1，我“同意”你的关闭请求；</p></li> <li><p>第三次挥手(FIN=1，seq=y)</p> <p>主机2向主机1发送FIN报文段，请求关闭连接，同时主机2进入<code>LAST_ACK</code> 状态</p></li> <li><p>第四次挥手(ACK=1，ACKnum=y+1)</p> <p>主机1收到主机2发送的FIN报文段，向主机2发送ACK报文段，然后主机1进入<code>TIME_WAIT</code>状态；主机2收到主机1的ACK报文段以后，就关闭连接；此时，<strong>主机1等待2MSL后依然没有收到回复</strong>，则证明Server端已正常关闭，那好，主机1也可以关闭连接了，进入 <code>CLOSED</code> 状态。</p> <p>主机 1 等待了某个固定时间（两个最大段生命周期，2MSL，2 Maximum Segment Lifetime）之后，没有收到服务器端的 ACK ，认为服务器端已经正常关闭连接，于是自己也关闭连接，进入 <code>CLOSED</code> 状态。</p></li></ul> <blockquote><p>为什么连接的时候是三次握手，关闭的时候却是四次握手？</p></blockquote> <p>因为当Server端收到Client端的SYN连接请求报文后，可以直接发送SYN+ACK报文。其中ACK报文是用来应答的，SYN报文是用来同步的。但是关闭连接时，当Server端收到FIN报文时，很可能并不会立即关闭SOCKET，所以只能先回复一个ACK报文，告诉Client端，&quot;你发的FIN报文我收到了&quot;。只有等到我Server端所有的报文都发送完了，我才能发送FIN报文，因此不能一起发送。故需要四步握手。</p> <p>由于 TCP 协议是全双工的，也就是说客户端和服务端都可以发起断开连接。两边各发起一次断开连接的申请，加上各自的两次确认，看起来就像执行了四次挥手。</p> <blockquote><p><strong>为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态？</strong></p></blockquote> <p>虽然按道理，四个报文都发送完毕，我们可以直接进入CLOSE状态了，但是我们必须假象网络是不可靠的，有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。</p> <p>还有一个原因，防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后，在这个2MSL时间中，就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。</p> <h3 id="tcp协议如何来保证传输的可靠性"><a href="#tcp协议如何来保证传输的可靠性" class="header-anchor">#</a> TCP协议如何来保证传输的可靠性</h3> <p>对于可靠性，TCP通过以下方式进行保证：</p> <ul><li><p>数据包校验：目的是检测数据在传输过程中的任何变化，若校验出包有错，则丢弃报文段并且不给出响应，这时TCP发送数据端超时后会重发数据；</p></li> <li><p>对失序数据包重排序：既然TCP报文段作为IP数据报来传输，而IP数据报的到达可能会失序，因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序，然后才交给应用层；</p></li> <li><p>丢弃重复数据：对于重复数据，能够丢弃重复数据；</p></li> <li><p>应答机制：当TCP收到发自TCP连接另一端的数据，它将发送一个确认。这个确认不是立即发送，通常将推迟几分之一秒；</p></li> <li><p>超时重发：当TCP发出一个段后，它启动一个定时器，等待目的端确认收到这个报文段。如果不能及时收到一个确认，将重发这个报文段；</p></li> <li><p>流量控制：TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据，这可以防止较快主机致使较慢主机的缓冲区溢出，这就是流量控制。TCP使用的流量控制协议是可变大小的滑动窗口协议。</p></li></ul> <blockquote><p>详细讲一下TCP的滑动窗口</p></blockquote> <h3 id="滑动窗口机制"><a href="#滑动窗口机制" class="header-anchor">#</a> 滑动窗口机制</h3> <p>如果发送方把数据发送得过快，接收方可能会来不及接收，这就会造成数据的丢失。所谓<strong>流量控制</strong>就是让发送方的发送速率不要太快，要让接收方来得及接收。</p> <p>利用<strong>滑动窗口机制</strong>可以很方便地在TCP连接上实现对发送方的流量控制。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds6d75md5j30si0ermyk.jpg" alt=""></p> <p>从上面的图可以看到滑动窗口左边的是已发送并且被确认的分组，滑动窗口右边是还没有轮到的分组。滑动窗口里面也分为两块，一块是已经发送但是未被确认的分组，另一块是窗口内等待发送的分组。随着已发送的分组不断被确认，窗口内等待发送的分组也会不断被发送。整个窗口就会往右移动，让还没轮到的分组进入窗口内。</p> <p>可以看到滑动窗口起到了一个限流的作用，也就是说当前滑动窗口的大小决定了当前 TCP 发送包的速率，而滑动窗口的大小取决于拥塞控制窗口和流量控制窗口的两者间的最小值。</p> <h4 id="流量控制"><a href="#流量控制" class="header-anchor">#</a> 流量控制</h4> <p>TCP 是全双工的，客户端和服务器均可作为发送方或接收方，我们现在假设一个发送方向接收方发送数据的场景来讲解流量控制。首先我们的接收方有一块接收缓存，当数据来到时会先把数据放到缓存中，上层应用等缓存中有数据时就会到缓存中取数据。假如发送方没有限制地不断地向接收方发送数据，接收方的应用程序又没有及时把接收缓存中的数据读走，就会出现缓存溢出，数据丢失的现象，为了解决这个问题，我们引入流量控制窗口。</p> <p>假设应用程序最后读走的数据序号是 lastByteRead，接收缓存中接收到的最后一个数据序号是 lastByteRcv，接收缓存的大小为 RcvSize，那么必须要满足 <code>lastByteRcv - lastByteRead &lt;= RcvSize</code> 才能保证接收缓存不会溢出，所以我们定义流量窗口为接收缓存剩余的空间，也就是 <code>Rcv = RcvSize - (lastByteRcv - lastByteRead)</code>。只要接收方在响应 ACK 的时候把这个窗口的值带给发送方，发送方就能知道接收方的接收缓存还有多大的空间，进而设置滑动窗口的大小。</p> <h4 id="拥塞控制"><a href="#拥塞控制" class="header-anchor">#</a> 拥塞控制</h4> <p>拥塞控制是指发送方先设置一个小的窗口值作为发送速率，当成功发包并接收到 ACK 时，便以指数速率增大发送窗口的大小，直到遇到丢包（超时/三个冗余ACK），才停止并调整窗口的大小。这么做能最大限度地利用带宽，又不至于让网络环境变得太过拥挤。</p> <p>最终滑动窗口的值将设置为流量控制窗口和拥塞控制窗口中的较小值。</p> <h3 id="tcp的拥塞处理"><a href="#tcp的拥塞处理" class="header-anchor">#</a> TCP的拥塞处理</h3> <p>计算机网络中的带宽、交换结点中的缓存及处理机等都是网络的资源。在某段时间，若对网络中某一资源的需求超过了该资源所能提供的可用部分，网络的性能就会变坏，这种情况就叫做拥塞。拥塞控制就是防止过多的数据注入网络中，这样可以使网络中的路由器或链路不致过载。注意，拥塞控制和流量控制不同，前者是一个全局性的过程，而后者指点对点通信量的控制。拥塞控制的方法主要有以下四种：</p> <ol><li>慢启动：不要一开始就发送大量的数据，先探测一下网络的拥塞程度，也就是说由小到大逐渐增加拥塞窗口的大小;</li> <li>拥塞避免：拥塞避免算法让拥塞窗口缓慢增长，即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加1，而不是加倍，这样拥塞窗口按线性规律缓慢增长。</li> <li>快重传：快重传要求接收方在收到一个失序的报文段后就立即发出重复确认（为的是使发送方及早知道有报文段没有到达对方）而不要等到自己发送数据时捎带确认。快重传算法规定，发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段，而不必继续等待设置的重传计时器时间到期。</li> <li>快恢复：快重传配合使用的还有快恢复算法，当发送方连续收到三个重复确认时，就执行“乘法减小”算法，把ssthresh 门限减半，但是接下去并不执行慢开始算法：因为如果网络出现拥塞的话就不会收到好几个重复的确认，所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法，而是将 cwnd 设置为ssthresh 的大小，然后执行拥塞避免算法。</li></ol> <h3 id="服务器出现了大量close-wait状态如何解决"><a href="#服务器出现了大量close-wait状态如何解决" class="header-anchor">#</a> 服务器出现了大量CLOSE_WAIT状态如何解决</h3> <p>大量 CLOSE_WAIT 表示程序出现了问题，对方的 socket 已经关闭连接，而我方忙于读或写没有及时关闭连接，需要检查代码，特别是释放资源的代码，或者是处理请求的线程配置。</p> <h3 id="讲一讲syn超时-洪泛攻击-以及解决策略"><a href="#讲一讲syn超时-洪泛攻击-以及解决策略" class="header-anchor">#</a> 讲一讲SYN超时，洪泛攻击，以及解决策略</h3> <p>什么 SYN 是洪泛攻击？ 在 TCP 的三次握手机制的第一步中，客户端会向服务器发送 SYN 报文段。服务器接收到 SYN 报文段后会为该 TCP 分配缓存和变量，如果攻击分子大量地往服务器发送 SYN 报文段，服务器的连接资源终将被耗尽，导致内存溢出无法继续服务。</p> <p>解决策略： 当服务器接受到 SYN 报文段时，不直接为该 TCP 分配资源，而只是打开一个半开的套接字。接着会使用 SYN 报文段的源 Id，目的 Id，端口号以及只有服务器自己知道的一个秘密函数生成一个 cookie，并把 cookie 作为序列号响应给客户端。</p> <p>如果客户端是正常建立连接，将会返回一个确认字段为 cookie + 1 的报文段。接下来服务器会根据确认报文的源Id，目的 Id，端口号以及秘密函数计算出一个结果，如果结果的值 +1等于确认字段的值，则证明是刚刚请求连接的客户端，这时候才为该 TCP 分配资源</p> <p>这样一来就不会为恶意攻击的 SYN 报文段分配资源空间，避免了攻击。</p> <h2 id="三、http"><a href="#三、http" class="header-anchor">#</a> 三、HTTP</h2> <blockquote><p>HTTP1.0、HTTP1.1、HTTP2.0 的区别</p> <p>post 和 get 的区别</p></blockquote> <p>HTTP 全称是 HyperText Transfer Protocal，即：超文本传输协议。是互联网上应用最为广泛的一种<strong>网络通信协议</strong>，它允许将超文本标记语言（HTML）文档从 Web 服务器传送到客户端的浏览器。目前我们使用的是<strong>HTTP/1.1 版本</strong>。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人 Ted Nelson 构思了一种通过计算机处理文本信息的方法，并称之为超文本（hypertext），这成为了HTTP超文本传输协议标准架构的发展根基。</p> <h3 id="uri-和-url"><a href="#uri-和-url" class="header-anchor">#</a> URI 和 URL</h3> <p>每个Web 服务器资源都有一个名字，这样客户端就可以说明他们感兴趣的资源是什么了，服务器资源名被称为统一资源标识符（Uniform Resource Identifier,URI）。URI 就像因特网上的邮政地址一样，在世界范围内唯一标识并定位信息资源。</p> <p>统一资源定位符（URL）是资源标识符最常见的形式。 URL 描述了一台特定服务器上某资源的特定位置。</p> <p>现在几乎所有的 URI 都是 URL。</p> <p>URI 的第二种形式就是统一资源名（URN）。URN 是作为特定内容的唯一名称使用的，与目前的资源所在地无关。</p> <h3 id="http消息的结构"><a href="#http消息的结构" class="header-anchor">#</a> HTTP消息的结构</h3> <p><strong>事务和报文</strong></p> <p>客户端是怎样通过 HTTP 与 Web 服务器及其资源进行事务处理的呢？一个 <strong>HTTP 事务</strong>由一条请求命令（从客户端发往服务器）和一个响应（从服务器发回客户端）结果组成。这种通信是通过名为<strong>HTTP报文</strong>（HTTP Message）的格式化数据块进行的。</p> <h4 id="http事务"><a href="#http事务" class="header-anchor">#</a> HTTP事务：</h4> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds68n7iduj30jx08caag.jpg" alt=""></p> <h4 id="报文"><a href="#报文" class="header-anchor">#</a> 报文：</h4> <p>HTTP 报文是纯文本，不是二进制代码。从 Web 客户端发往 Web 服务器的 HTTP 报文称为请求报文（request message）。从服务器发往客户端的报文称为响应报文。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gdpnh0qepnj30p006eacq.jpg" alt=""></p> <p>HTTP 报文包括三部分：</p> <ul><li>起始行</li> <li>首部字段</li> <li>主体</li></ul> <h4 id="常见http-首部字段"><a href="#常见http-首部字段" class="header-anchor">#</a> 常见HTTP 首部字段：</h4> <p><strong>a、通用首部字段</strong>（请求报文与响应报文都会使用的首部字段）</p> <ul><li>Date：创建报文时间</li> <li>Connection：连接的管理</li> <li>Cache-Control：缓存的控制</li> <li>Transfer-Encoding：报文主体的传输编码方式</li></ul> <p><strong>b、请求首部字段</strong>（请求报文会使用的首部字段）</p> <ul><li>Host：请求资源所在服务器</li> <li>Accept：可处理的媒体类型</li> <li>Accept-Charset：可接收的字符集</li> <li>Accept-Encoding：可接受的内容编码</li> <li>Accept-Language：可接受的自然语言</li></ul> <p>**c、响应首部字段（**响应报文会使用的首部字段）</p> <ul><li>Accept-Ranges：可接受的字节范围</li> <li>Location：令客户端重新定向到的URI</li> <li>Server：HTTP服务器的安装信息</li></ul> <p><strong>d、实体首部字段</strong>（请求报文与响应报文的的实体部分使用的首部字段）</p> <ul><li>Allow：资源可支持的HTTP方法</li> <li>Content-Type：实体主类的类型</li> <li>Content-Encoding：实体主体适用的编码方式</li> <li>Content-Language：实体主体的自然语言</li> <li>Content-Length：实体主体的的字节数</li> <li>Content-Range：实体主体的位置范围，一般用于发出部分请求时使用</li></ul> <h3 id="方法"><a href="#方法" class="header-anchor">#</a> 方法</h3> <p>Http 协议定义了很多与服务器交互的方法，最基本的有 4 种，分别是 <strong>GET,POST,PUT,DELETE</strong>. 一个 URL 地址用于描述一个网络上的资源，而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查，改，增，删4个操作。 我们最常见的就是 GET 和 POST 了。GET 一般用于获取/查询资源信息，而 POST 一般用于更新资源信息。</p> <ul><li>GET</li> <li>HEAD</li> <li>PUT</li> <li>POST</li> <li>TRACE</li> <li>OPTIONS</li> <li>DELETE</li></ul> <h3 id="get与post的区别"><a href="#get与post的区别" class="header-anchor">#</a> GET与POST的区别</h3> <p>GET与POST是我们常用的两种HTTP Method，二者之间的区别主要包括如下五个方面：</p> <ol><li>从功能上讲，GET一般用来从服务器上获取资源，POST一般用来更新服务器上的资源；</li> <li>从REST服务角度上说，GET是幂等的，即读取同一个资源，总是得到相同的数据，而POST不是幂等的，因为每次请求对资源的改变并不是相同的；进一步地，GET不会改变服务器上的资源，而POST会对服务器资源进行改变；</li> <li>从请求参数形式上看，GET请求的数据会附在URL之后，即将请求数据放置在HTTP报文的 请求头 中，以?分割URL和传输数据，参数之间以&amp;相连。特别地，如果数据是英文字母/数字，原样发送；否则，会将其编码为 application/x-www-form-urlencoded MIME 字符串(如果是空格，转换为+，如果是中文/其他字符，则直接把字符串用BASE64加密，得出如：%E4%BD%A0%E5%A5%BD，其中％XX中的XX为该符号以16进制表示的ASCII)；而POST请求会把提交的数据则放置在是HTTP请求报文的 请求体 中。</li> <li>就安全性而言，POST的安全性要比GET的安全性高，因为GET请求提交的数据将明文出现在URL上，而且POST请求参数则被包装到请求体中，相对更安全。</li> <li>从请求的大小看，GET请求的长度受限于浏览器或服务器对URL长度的限制，允许发送的数据量比较小，而POST请求则是没有大小限制的。</li></ol> <p>HTTP请求结构： 请求方式 + 请求URI + 协议及其版本</p> <p>HTTP响应结构： 状态码 + 原因短语 + 协议及其版本</p> <h3 id="状态码"><a href="#状态码" class="header-anchor">#</a> 状态码</h3> <p>每条HTTP响应报文返回时都会携带一个状态码。状态码是一个三位数字的代码，告知客户端请求是否成功，或者是都需要采取其他动作。</p> <ul><li><p>1xx：表明服务端接收了客户端请求，客户端继续发送请求；</p></li> <li><p>2xx：客户端发送的请求被服务端成功接收并成功进行了处理；</p></li> <li><p>3xx：服务端给客户端返回用于重定向的信息；</p></li> <li><p>4xx：客户端的请求有非法内容；</p></li> <li><p>5xx：服务端未能正常处理客户端的请求而出现意外错误。</p></li> <li><p><strong>200 OK</strong>：表示从客户端发送给服务器的请求被正常处理并返回；</p></li> <li><p><strong>204 No Content</strong>：表示客户端发送给客户端的请求得到了成功处理，但在返回的响应报文中不含实体的主体部分（没有资源可以返回）</p></li> <li><p><strong>206 Patial Content</strong>：表示客户端进行了范围请求，并且服务器成功执行了这部分的GET请求，响应报文中包含由Content-Range指定范围的实体内容。</p></li> <li><p><strong>301 Moved Permanently</strong>：永久性重定向，表示请求的资源被分配了新的URL，之后应使用更改的URL；</p></li> <li><p><strong>302 Found</strong>：临时性重定向，表示请求的资源被分配了新的URL，希望本次访问使用新的URL；</p></li> <li><p><strong>303 See Other</strong>：表示请求的资源被分配了新的URL，应使用GET方法定向获取请求的资源</p></li> <li><p>304 Not Modified：表示客户端发送附带条件（是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部）的请求时，服务器端允许访问资源，但是请求为满足条件的情况下返回改状态码；</p></li> <li><p><strong>400 Bad Request</strong>:表示请求报文中存在语法错误；</p></li> <li><p><strong>401 Unauthorized</strong>：未经许可，需要通过HTTP认证；</p></li> <li><p><strong>403 Forbidden</strong>：服务器拒绝该次访问（访问权限出现问题）</p></li> <li><p><strong>404 Not Found</strong>：表示服务器上无法找到请求的资源，除此之外，也可以在服务器拒绝请求但不想给拒绝原因时使用；</p></li> <li><p><strong>500 Inter Server Error</strong>：表示服务器在执行请求时发生了错误，也有可能是web应用存在的bug或某些临时的错误时；</p></li> <li><p><strong>503 Server Unavailable</strong>：表示服务器暂时处于超负载或正在进行停机维护，无法处理请求；</p></li></ul> <p>HTTP 是个应用层协议。HTTP 无需操心网络通信的具体细节，而是把这些细节都交给了通用可靠的因特网传输协议 TCP/IP。</p> <p>在 HTTP 客户端向服务器发送报文之前，需要用网络协议（Internet Protocol，IP）地址和端口号在客户端和服务器之间建立一条 TCP/IP 协议。而 IP 地址就是通过 URL 提供的，像 <code>http://207.200.21.11:80/index.html</code>，还有使用域名服务（Domain Name Services，DNS）的 <code>http://www.lazyegg.net</code>。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gdpo1kf1lhj30rq0p8k4t.jpg" alt=""></p> <h3 id="协议版本"><a href="#协议版本" class="header-anchor">#</a> 协议版本</h3> <ul><li><p><strong>HTTP/0.9</strong></p> <p>HTTP协议的最初版本，功能简陋，仅支持 GET 方法，并且仅能请求访问 HTML 格式的资源</p></li> <li><p><strong>HTTP/1.0</strong></p> <ul><li>增加了请求方式 POST 和 HEAD</li> <li>不再局限于0.9版本的HTML格式，根据Content-Type可以支持多种数据格式，即MIME多用途互联网邮件扩展，例如text/html、image/jpeg等</li> <li>同时也开始支持 cache，就是当客户端在规定时间内访问统一网站，直接访问cache即可</li> <li>HTTP请求和回应的格式也变了。除了数据部分，每次通信都必须包括头信息（HTTP header），用来描述一些元数据。其他的新增功能还包括状态码（status code）、多字符集支持、多部分发送（multi-part type）、权限（authorization）、缓存（cache）、内容编码（content encoding）等</li> <li>但是1.0版本的工作方式是每次TCP连接只能发送一个请求，当服务器响应后就会关闭这次连接，下一个请求需要再次建立TCP连接，就是不支持keepalive</li></ul></li> <li><p><strong>HTTP/1.0+</strong></p> <p>在20世纪90年代中叶，为满足飞快发展的万维网，很多流行的 Web 客户端和服务器飞快的向 HTTP 中添加各种特性，包括持久的 keep-alive 连接、虚拟主机支持，以及代理连接支持都被假如到 HTTP 中，并称为非官方的事实标准。这种非正式的 HTTP 扩展版本通常称为 HTTP/1.0+</p></li> <li><p><strong>HTTP/1.1</strong></p> <ul><li>http1.1是目前最为主流的http协议版本，从1997年发布至今，仍是主流的http协议版本。</li> <li>引入了持久连接，或叫长连接（ persistent connection），即TCP连接默认不关闭，可以被多个请求复用，不用声明Connection: keep-alive。</li> <li>引入了管道机制（ pipelining），即在同一个TCP连接里，客户端可以同时发送多个请求，进一步改进了HTTP协议的效率。</li> <li>新增方法：PUT、 PATCH、 OPTIONS、 DELETE。</li> <li>http协议不带有状态，每次请求都必须附上所有信息。请求的很多字段都是重复的，浪费带宽，影响速度。</li></ul></li> <li><p><strong>HTTP/2.0（又名 HTTP-NG）</strong></p> <ul><li>http/2发布于2015年，目前应用还比较少。</li> <li>http/2是一个彻底的二进制协议，头信息和数据体都是二进制，并且统称为&quot;帧&quot;（frame）：头信息帧和数据帧。</li> <li>复用TCP连接，在一个连接里，客户端和浏览器都可以同时发送多个请求或回应，且不用按顺序一一对应，避免了队头堵塞的问题,此双向的实时通信称为多工（ Multiplexing）。</li> <li>HTTP/2 允许服务器未经请求，主动向客户端发送资源，即服务器推送。</li> <li>引入头信息压缩机制（ header compression） ,头信息使用gzip或compress压缩后再发送。</li></ul></li></ul> <h2 id="四、https"><a href="#四、https" class="header-anchor">#</a> 四、HTTPS</h2> <p>HTTP缺点：</p> <ol><li>通信使用明文不对数据进行加密（内容容易被窃听）</li> <li>不验证通信方身份（容易伪装）</li> <li>无法确定报文完整性（内容易被篡改）</li></ol> <p>因此，HTTP 协议不适合传输一些敏感信息，比如：信用卡号、密码等支付信息。</p> <p>为了解决 HTTP 协议的这一缺陷，需要使用另一种协议：安全套接字层超文本传输协议 HTTPS，为了数据传输的安全，HTTPS 在 HTTP 的基础上加入了 SSL（安全套接层）协议，SSL 依靠证书来验证服务器的身份，并为浏览器和服务器之间的通信加密。</p> <p><strong>与 SSL（安全套接层）组合使用的 HTTP 就是 HTTPS</strong></p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gdrb5imj5uj30ro0aqq6q.jpg" alt=""></p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds4ejm6cuj30r60cm40n.jpg" alt="img"></p> <h3 id="http-和-https-对比"><a href="#http-和-https-对比" class="header-anchor">#</a> HTTP 和 HTTPS 对比</h3> <p>HTTP 协议传输的数据都是未加密的，也就是明文的，因此使用 HTTP 协议传输隐私信息非常不安全，为了保证这些隐私数据能加密传输，于是网景公司设计了 SSL（Secure Sockets Layer）协议用于对 HTTP 协议传输的数据进行加密，从而就诞生了 HTTPS。简单来说，HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议，要比 HTTP 协议安全。</p> <p>HTTPS 和 HTTP 的区别主要如下：</p> <ol><li>https协议需要到ca申请证书，一般免费证书较少，因而需要一定费用。</li> <li>http是超文本传输协议，信息是明文传输，https则是具有安全性的ssl加密传输协议。</li> <li>http和https使用的是完全不同的连接方式，用的端口也不一样，前者是80，后者是443。</li> <li>http的连接很简单，是无状态的；HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议，比http协议安全。</li></ol> <h3 id="对称加密与非对称加密"><a href="#对称加密与非对称加密" class="header-anchor">#</a> 对称加密与非对称加密</h3> <p>主要的加密方法分为两种：一种是共享密钥加密（对称密钥加密），一种是公开密钥加密（非对称密钥加密）</p> <h4 id="共享密钥加密-对称秘钥加密"><a href="#共享密钥加密-对称秘钥加密" class="header-anchor">#</a> 共享密钥加密(对称秘钥加密)</h4> <p>加密与解密使用同一个密钥，常见的对称加密算法：DES，AES，3DES等。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds4ee4n2nj30pd0fhgoc.jpg" alt="img"></p> <p>也就是说在加密的同时，也会把密钥发送给对方。在发送密钥过程中可能会造成密钥被窃取，那么如何解决这一问题呢？</p> <h4 id="公开密钥-非对称密钥"><a href="#公开密钥-非对称密钥" class="header-anchor">#</a> 公开密钥（非对称密钥）</h4> <p>公开密钥使用一对非对称密钥。一把叫私有密钥，另一把叫公开密钥。私有密钥不让任何人知道，公有密钥随意发送。公钥加密的信息，只有私钥才能解密。常见的非对称加密算法：RSA，ECC等。</p> <p>也就是说，发送密文方使用对方的公开密钥进行加密，对方接受到信息后，使用私有密钥进行解密。</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds4ewaqefj30ff0bpjtq.jpg" alt=""></p> <p>对称加密加密与解密使用的是同样的密钥，所以速度快，但由于需要将密钥在网络传输，所以安全性不高。</p> <p>非对称加密使用了一对密钥，公钥与私钥，所以安全性高，但加密与解密速度慢。</p> <p>为了解决这一问题，https 采用对称加密与非对称加密的混合加密方式。</p> <h3 id="ssl-tsl"><a href="#ssl-tsl" class="header-anchor">#</a> SSL/TSL</h3> <p>SSL（Secure Sockets Layer），中文叫做“安全套接层”。它是在上世纪90年代中期，由网景公司设计的。</p> <p>SSL 协议就是用来解决 HTTP 传输过程的不安全问题，到了1999年，SSL 因为应用广泛，已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS（是“Transport Layer Security”的缩写），中文叫做“传输层安全协议”。</p> <p>很多相关的文章都把这两者并列称呼（SSL/TLS），因为这两者可以视作同一个东西的不同阶段。</p> <p>SSL/TLS协议的基本思路是采用<a href="http://en.wikipedia.org/wiki/Public-key_cryptography" target="_blank" rel="noopener noreferrer">公钥加密法<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，也就是说，客户端先向服务器端索要公钥，然后用公钥加密信息，服务器收到密文后，用自己的私钥解密。</p> <p>但是，这里有两个问题。</p> <ul><li><strong>如何保证公钥不被篡改？</strong></li></ul> <p>​	解决方法：将公钥放在数字证书中。只要证书是可信的，公钥就是可信的。</p> <ul><li><p><strong>公钥加密计算量太大，如何减少耗用的时间？</strong></p> <p>每一次对话（session），客户端和服务器端都生成一个&quot;对话密钥&quot;（session key），用它来加密信息。由于&quot;对话密钥&quot;是对称加密，所以运算速度非常快，而服务器公钥只用于加密&quot;对话密钥&quot;本身，这样就减少了加密运算的消耗时间。</p></li></ul> <p>因此，SSL/TLS协议的基本过程是这样的：</p> <ol><li><p>服务端将非对称加密的公钥发送给客户端；</p></li> <li><p>客户端拿着服务端发来的公钥，对对称加密的key做加密并发给服务端；</p></li> <li><p>服务端拿着自己的私钥对发来的密文解密，从而获取到对称加密的key；</p></li> <li><p>二者利用对称加密的key对需要传输的消息做加解密传输。</p></li></ol> <p>HTTPS 相比 HTTP，在请求前多了一个「握手」的环节。</p> <p>握手过程中确定了数据加密的密码。在握手过程中，网站会向浏览器发送 SSL 证书，SSL 证书和我们日常用的身份证类似，是一个支持 HTTPS 网站的身份证明，SSL 证书里面包含了网站的域名，证书有效期，证书的颁发机构以及用于加密传输密码的公钥等信息，由于公钥加密的密码只能被在申请证书时生成的私钥解密，因此浏览器在生成密码之前需要先核对当前访问的域名与证书上绑定的域名是否一致，同时还要对证书的颁发机构进行验证，如果验证失败浏览器会给出证书错误的提示。</p> <h3 id="证书"><a href="#证书" class="header-anchor">#</a> 证书</h3> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds4f2pq0cj30bc0d2dg2.jpg" alt=""></p> <p>实际上，我们使用的证书分很多种类型，SSL证书只是其中的一种。证书的格式是由 X.509 标准定义。SSL 证书负责传输公钥，是一种PKI（Public Key Infrastructure，公钥基础结构）证书。</p> <p>我们常见的证书根据用途不同大致有以下几种：</p> <ol><li>SSL证书，用于加密HTTP协议，也就是HTTPS。</li> <li>代码签名证书，用于签名二进制文件，比如Windows内核驱动，Firefox插件，Java代码签名等等。</li> <li>客户端证书，用于加密邮件。</li> <li>双因素证书，网银专业版使用的USB Key里面用的就是这种类型的证书。</li></ol> <p>这些证书都是由受认证的证书颁发机构——我们称之为CA（Certificate Authority）机构来颁发，针对企业与个人的不同，可申请的证书的类型也不同，价格也不同。CA机构颁发的证书都是受信任的证书，对于 SSL 证书来说，如果访问的网站与证书绑定的网站一致就可以通过浏览器的验证而不会提示错误。</p> <p><strong>为什么服务端要发送证书给客户端</strong></p> <p>互联网有太多的服务需要使用证书来验证身份，以至于客户端(操作系统或浏览器等)无法内置所有证书，需要通过服务端将证书发送给客户端。</p> <p><strong>客户端为什么要验证接收到的证书</strong></p> <p>中间人攻击</p> <div class="language- extra-class"><pre class="language-text"><code>客户端&lt;------------攻击者&lt;------------服务端
        伪造证书            拦截请求
</code></pre></div><p><strong>客户端如何验证接收到的证书</strong></p> <p>为了回答这个问题，需要引入数字签名(Digital Signature)。</p> <div class="language- extra-class"><pre class="language-text"><code>+---------------------+
| A digital signature |
|(not to be confused  |
|with a digital       |
|certificate)         |            +---------+              +--------+
| is a mathematical   |----哈希---&gt;| 消息摘要  |---私钥加密---&gt;| 数字签名 |
|technique used       |            +---------+              +--------+
|to validate the      |
|authenticity and     |
|integrity of a       |
|message, software    |
|or digital document. |
+---------------------+
</code></pre></div><p>将一段文本通过哈希（hash）和私钥加密处理后生成数字签名。</p> <p>假设消息传递在Bob，Susan和Pat三人之间发生。Susan将消息连同数字签名一起发送给Bob，Bob接收到消息后，可以这样验证接收到的消息就是Susan发送的</p> <div class="language- extra-class"><pre class="language-text"><code>+---------------------+
| A digital signature |
|(not to be confused  |
|with a digital       |
|certificate)         |            +---------+
| is a mathematical   |----哈希---&gt;|  消息摘要 |
|technique used       |            +---------+
|to validate the      |                 |
|authenticity and     |                 |
|integrity of a       |                 |
|message, software    |                 对
|or digital document. |                 比
+---------------------+                 |
                                        |
                                        |
          +--------+               +---------+
          | 数字签名 |---公钥解密---&gt;|  消息摘要 |
          +--------+               +---------+
</code></pre></div><p>当然，这个前提是Bob知道Susan的公钥。更重要的是，和消息本身一样，公钥不能在不安全的网络中直接发送给Bob。此时就引入了<a href="https://en.wikipedia.org/wiki/Certificate_authority" target="_blank" rel="noopener noreferrer">证书颁发机构<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>（Certificate Authority，简称CA），CA数量并不多，Bob客户端内置了所有受信任CA的证书。CA对Susan的公钥（和其他信息）数字签名后生成证书。</p> <p>Susan将证书发送给Bob后，Bob通过CA证书的公钥验证证书签名。</p> <p>Bob信任CA，CA信任Susan 使得 Bob信任Susan，<a href="https://en.wikipedia.org/wiki/Chain_of_trust" target="_blank" rel="noopener noreferrer">信任链<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>（Chain Of Trust）就是这样形成的。</p> <p>事实上，Bob客户端内置的是CA的根证书(Root Certificate)，HTTPS协议中服务器会发送证书链（Certificate Chain）给客户端。</p> <h3 id="https的工作原理"><a href="#https的工作原理" class="header-anchor">#</a> HTTPS的工作原理</h3> <ol><li>Client 使用 https 的 URL 访问 Server，要求与 Server 建立 SSL 连接</li> <li>Server 把事先配置好的公钥证书返回给客户端。</li> <li>Client 验证公钥证书：比如是否在有效期内，证书的用途是不是匹配 Client 请求的站点，是不是在 CRL 吊销列表里面，它的上一级证书是否有效，这是一个递归的过程，直到验证到根证书（操作系统内置的Root证书或者Client内置的Root证书）。如果验证通过则继续，不通过则显示警告信息。</li> <li>Client 使用伪随机数生成器生成加密所使用的对称密钥，然后用证书的公钥加密这个对称密钥，发给Server。</li> <li>Server使用自己的私钥（private key）解密这个消息，得到对称密钥。至此，Client和Server双方都持有了相同的对称密钥。</li> <li>Server使用对称密钥加密“明文内容A”，发送给Client。</li> <li>Client使用对称密钥解密响应的密文，得到“明文内容A”。</li> <li>Client再次发起HTTPS的请求，使用对称密钥加密请求的“明文内容B”，然后Server使用对称密钥解密密文，得到“明文内容B”。</li></ol> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gdqyp5t210j31ey0u0n0y.jpg" alt=""></p> <h3 id="https的优点"><a href="#https的优点" class="header-anchor">#</a> HTTPS的优点</h3> <p>尽管 HTTPS 并非绝对安全，掌握根证书的机构、掌握加密算法的组织同样可以进行中间人形式的攻击，但 HTTPS仍是现行架构下最安全的解决方案，主要有以下几个好处：</p> <ol><li>使用HTTPS协议可认证用户和服务器，确保数据发送到正确的客户机和服务器；</li> <li>HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议，要比http协议安全，可防止数据在传输过程中不被窃取、改变，确保数据的完整性。</li> <li>HTTPS是现行架构下最安全的解决方案，虽然不是绝对安全，但它大幅增加了中间人攻击的成本。</li> <li>谷歌曾在2014年8月份调整搜索引擎算法，并称“比起同等HTTP网站，采用HTTPS加密的网站在搜索结果中的排名将会更高”。</li></ol> <h3 id="https的缺点"><a href="#https的缺点" class="header-anchor">#</a> HTTPS的缺点</h3> <p>虽然说HTTPS有很大的优势，但其相对来说，还是存在不足之处的：</p> <ol><li>HTTPS协议握手阶段比较费时，会使页面的加载时间延长近50%，增加10%到20%的耗电；</li> <li>HTTPS连接缓存不如HTTP高效，会增加数据开销和功耗，甚至已有的安全措施也会因此而受到影响；</li> <li>SSL证书需要钱，功能越强大的证书费用越高，个人网站、小网站没有必要一般不会用。</li> <li>SSL证书通常需要绑定IP，不能在同一IP上绑定多个域名，IPv4资源不可能支撑这个消耗。</li> <li>HTTPS协议的加密范围也比较有限，在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的，SSL证书的信用链体系并不安全，特别是在某些国家可以控制CA根证书的情况下，中间人攻击一样可行。</li></ol> <h3 id="http-切换到-https"><a href="#http-切换到-https" class="header-anchor">#</a> HTTP 切换到 HTTPS</h3> <p>如果需要将网站从http切换到https到底该如何实现呢？</p> <p>这里需要将页面中所有的链接，例如js，css，图片等等链接都由http改为https。例如：http://www.baidu.com改为https://www.baidu.com</p> <p>BTW，这里虽然将http切换为了https，还是建议保留http。所以我们在切换的时候可以做http和https的兼容，具体实现方式是，去掉页面链接中的http头部，这样可以自动匹配http头和https头。例如：将http://www.baidu.com改为//www.baidu.com。然后当用户从http的入口进入访问页面时，页面就是http，如果用户是从https的入口进入访问页面，页面即使https的。</p> <h3 id="什么是cookie-cookie的使用过程是怎么样的"><a href="#什么是cookie-cookie的使用过程是怎么样的" class="header-anchor">#</a> 什么是Cookie，Cookie的使用过程是怎么样的？</h3> <p>由于 http 协议是无状态协议，如果客户通过浏览器访问 web 应用时没有一个保存用户访问状态的机制，那么将不能持续跟踪应用的操作。比如当用户往购物车中添加了商品，web 应用必须在用户浏览别的商品的时候仍保存购物车的状态，以便用户继续往购物车中添加商品。</p> <p>cookie 是浏览器的一种缓存机制，它可用于维持客户端与服务器端之间的会话。由于下面一题会讲到session，所以这里要强调cookie会将会话保存在客户端（session则是把会话保存在服务端）</p> <p>这里以最常见的登陆案例讲解cookie的使用过程：</p> <ol><li>首先用户在客户端浏览器向服务器发起登陆请求</li> <li>登陆成功后，服务端会把登陆的用户信息设置 cookie 中，返回给客户端浏览器</li> <li>客户端浏览器接收到 cookie 请求后，会把 cookie 保存到本地（可能是内存，也可能是磁盘，看具体使用情况而定）</li> <li>以后再次访问该 web 应用时，客户端浏览器就会把本地的 cookie 带上，这样服务端就能根据 cookie 获得用户信息了</li></ol> <h3 id="什么是session-有哪些实现session的机制"><a href="#什么是session-有哪些实现session的机制" class="header-anchor">#</a> 什么是session，有哪些实现session的机制？</h3> <p>session 是一种维持客户端与服务器端会话的机制。但是与 <strong>cookie 把会话信息保存在客户端本地不一样，session 把会话保留在浏览器端。</strong></p> <p>我们同样以登陆案例为例子讲解 session 的使用过程：</p> <ol><li>首先用户在客户端浏览器发起登陆请求</li> <li>登陆成功后，服务端会把用户信息保存在服务端，并返回一个唯一的 session 标识给客户端浏览器。</li> <li>客户端浏览器会把这个唯一的 session 标识保存在起来</li> <li>以后再次访问 web 应用时，客户端浏览器会把这个唯一的 session 标识带上，这样服务端就能根据这个唯一标识找到用户信息。</li></ol> <p>看到这里可能会引起疑问：把唯一的 session 标识返回给客户端浏览器，然后保存起来，以后访问时带上，这难道不是 cookie 吗？</p> <p>没错，s<strong>ession 只是一种会话机制，在许多 web 应用中，session 机制就是通过 cookie 来实现的</strong>。也就是说它只是使用了 cookie 的功能，并不是使用 cookie 完成会话保存。与 cookie 在保存客户端保存会话的机制相反，session 通过 cookie 的功能把会话信息保存到了服务端。</p> <p>进一步地说，session 是一种维持服务端与客户端之间会话的机制，它可以有不同的实现。以现在比较流行的小程序为例，阐述一个 session 的实现方案：</p> <ol><li>首先用户登陆后，需要把用户登陆信息保存在服务端，这里我们可以采用 redis。比如说给用户生成一个 userToken，然后以 userId 作为键，以 userToken 作为值保存到 redis 中，并在返回时把 userToken 带回给小程序端。</li> <li>小程序端接收到 userToken 后把它缓存起来，以后每当访问后端服务时就把 userToken 带上。</li> <li>在后续的服务中服务端只要拿着小程序端带来的 userToken 和 redis 中的 userToken 进行比对，就能确定用户的登陆状态了。</li></ol> <h3 id="session和cookie有什么区别"><a href="#session和cookie有什么区别" class="header-anchor">#</a> session和cookie有什么区别</h3> <p>经过上面两道题的阐述，这道题就很清晰了</p> <ol><li>cookie 是浏览器提供的一种缓存机制，它可以用于维持客户端与服务端之间的会话</li> <li>session 指的是维持客户端与服务端会话的一种机制，它可以通过 cookie 实现，也可以通过别的手段实现。</li> <li>如果用 cookie 实现会话，那么会话会保存在客户端浏览器中</li> <li>而 session 机制提供的会话是保存在服务端的。</li></ol> <h2 id="other-faq"><a href="#other-faq" class="header-anchor">#</a> Other FAQ</h2> <h3 id="从输入网址到获得页面的过程"><a href="#从输入网址到获得页面的过程" class="header-anchor">#</a> 从输入网址到获得页面的过程</h3> <ol><li>浏览器查询 DNS，获取域名对应的IP地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。对于向本地DNS服务器进行查询，如果要查询的域名包含在本地配置区域资源中，则返回解析结果给客户机，完成域名解析(此解析具有权威性)；如果要查询的域名不由本地DNS服务器区域解析，但该服务器已缓存了此网址映射关系，则调用这个IP地址映射，完成域名解析（此解析不具有权威性）。如果本地域名服务器并未缓存该网址映射关系，那么将根据其设置发起递归查询或者迭代查询；</li> <li>浏览器获得域名对应的IP地址以后，浏览器向服务器请求建立链接，发起三次握手；</li> <li>TCP/IP链接建立起来后，浏览器向服务器发送HTTP请求；</li> <li>服务器接收到这个请求，并根据路径参数映射到特定的请求处理器进行处理，并将处理结果及相应的视图返回给浏览器；</li> <li>浏览器解析并渲染视图，若遇到对js文件、css文件及图片等静态资源的引用，则重复上述步骤并向服务器请求这些资源；</li> <li>浏览器根据其请求到的资源、数据渲染页面，最终向用户呈现一个完整的页面。</li></ol> <p><strong>简单版</strong></p> <ol><li>DNS解析</li> <li>TCP连接</li> <li>发送HTTP请求</li> <li>服务器处理请求并返回HTTP报文</li> <li>浏览器解析渲染页面</li> <li>连接结束</li></ol> <h3 id="xss-攻击"><a href="#xss-攻击" class="header-anchor">#</a> XSS 攻击</h3> <p>XSS 是一种经常出现在web应用中的计算机安全漏洞，与 SQL 注入一起成为 web 中最主流的攻击方式。XSS 是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点，进而添加一些脚本代码嵌入到 web页面中去，使别的用户访问都会执行相应的嵌入代码，从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。</p> <p></p> <h3 id="ip地址的分类"><a href="#ip地址的分类" class="header-anchor">#</a> IP地址的分类</h3> <p>IP 地址是指互联网协议地址，是 IP 协议提供的一种统一的地址格式，它为互联网上的每一个网络和每一台主机分配一个逻辑地址，以此来屏蔽物理地址的差异。IP地址编址方案将IP地址空间划分为A、B、C、D、E五类，其中A、B、C是基本类，D、E类作为多播和保留使用，为特殊地址。</p> <p>每个IP地址包括两个标识码（ID），即网络ID和主机ID。同一个物理网络上的所有主机都使用同一个网络ID，网络上的一个主机（包括网络上工作站，服务器和路由器等）有一个主机ID与其对应。A~E类地址的特点如下：</p> <p>A类地址：以0开头，第一个字节范围：0~127；</p> <p>B类地址：以10开头，第一个字节范围：128~191；</p> <p>C类地址：以110开头，第一个字节范围：192~223；</p> <p>D类地址：以1110开头，第一个字节范围为224~239；</p> <p>E类地址：以1111开头，保留地址</p> <p><img src="https://tva1.sinaimg.cn/large/007S8ZIlly1gds4m1xeinj30ee0apdkh.jpg" alt=""></p> <h2 id="参考与感谢"><a href="#参考与感谢" class="header-anchor">#</a> 参考与感谢</h2> <ul><li>《HTTP 权威指南》</li> <li>https://arch-long.cn/articles/network/OSI模型TCPIP协议栈.html</li> <li>https://blog.csdn.net/qq_32998153/article/details/79680704</li></ul></div> <footer class="page-edit" style="display:none;"><!----> <!----></footer> <!----> <!----> <!----></main> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-db14854a data-v-db14854a><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-db14854a><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-db14854a></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-db14854a></path></svg></div><!----></div></div>
    <script src="/assets/js/app.447d4224.js" defer></script><script src="/assets/js/3.9d76740c.js" defer></script><script src="/assets/js/1.c4fd7d2e.js" defer></script><script src="/assets/js/106.a6cb54b0.js" defer></script>
  </body>
</html>
